package org.dbstar.scheduler.beans;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.dbstar.scheduler.identifier.DefaultIdentifier;
import org.dbstar.scheduler.identifier.Identifier;


/**
 * 复合Job，将多个子Job合成一个父Job
 * 
 * @author 代波
 * @since 1.0.0
 * @version 1.0.0
 * @date 2012-5-4
 */
public class CompoundJob extends Job {
	private static final long serialVersionUID = 8527222260415150295L;

	private CompoundJobResult result = new CompoundJobResult();

	private List<JobDefine> subJobs;

	@Override
	public final String getType() {
		return CompoundJobConf.JOB_TYPE;
	}

	@Override
	public final JobResult getResult() {
		return result;
	}

	public List<JobDefine> getSubJobs() {
		return subJobs;
	}

	public void setSubJobs(List<JobDefine> subJobs) {
		this.subJobs = subJobs;
	}

	@Override
	public final String getContent() {
		if (subJobs == null || subJobs.isEmpty()) {
			return null;
		} else {
			JSONArray array = new JSONArray();
			for (JobDefine define : subJobs) {
				array.add(buildJsonJob(define));
			}
			return array.toString();
		}
	}

	private static JSONObject buildJsonJob(JobDefine define) {
		JSONObject obj = new JSONObject();
		obj.element("identifier", define.getIdentifier().getStringIdentifier());
		Map<String, String> parameters = define.getParameters();
		if (parameters != null && !parameters.isEmpty()) {
			obj.element("parameters", parameters);
		}
		Set<Integer> dependencies = define.getDependencies();
		if (dependencies != null && !dependencies.isEmpty()) {
			obj.element("dependencies", StringUtils.join(dependencies, ','));
		}
		if (define.getCondition() != null) {
			obj.element("condition", define.getCondition());
		}
		obj.element("skip", define.isSkip());
		return obj;
	}

	@Override
	public final void setContent(String content) {
		if (!StringUtils.isBlank(content)) {
			this.subJobs = new ArrayList<JobDefine>();
			JSONArray array = JSONArray.fromObject(content);
			for (int i = 0, size = array.size(); i < size; i++) {
				JSONObject object = array.getJSONObject(i);
				Identifier identifier = DefaultIdentifier.valueOf(object.getString("identifier"));
				@SuppressWarnings("unchecked")
				Map<String, String> parameters = (Map<String, String>) object.opt("parameters");
				Set<Integer> dependencies = null;
				String ds = object.optString("dependencies", null);
				if (ds != null) {
					dependencies = new HashSet<Integer>();
					for (String s : StringUtils.split(ds, ',')) {
						dependencies.add(Integer.valueOf(s));
					}
				}
				String condition = object.optString("condition", null);
				boolean skip = object.optBoolean("skip", false);
				this.subJobs.add(new JobDefine(identifier, parameters, dependencies, condition, skip));
			}
		} else {
			this.subJobs = null;
		}
	}

	@Override
	public Job clone() throws CloneNotSupportedException {
		CompoundJob job = (CompoundJob) super.clone();
		job.result = (CompoundJobResult) this.result.clone();
		if (subJobs != null) {
			job.subJobs = new ArrayList<JobDefine>(subJobs.size());
			for (JobDefine jd : subJobs) {
				job.subJobs.add(jd.clone());
			}
		}
		return job;
	}
}
